﻿#include "pch.h"
#include "MainWindow.h"
#include "Resource.h"

BEGIN_MESSAGE_MAP(MainWindow, CDialog)
    ON_BN_CLICKED(IDC_BUTTON_MUSIC, OnButtonMusicClicked)
    ON_BN_CLICKED(IDC_BUTTON_PAUSE, OnButtonPauseClicked)
    ON_BN_CLICKED(IDC_BUTTON_START, OnButtonStartClicked)
    ON_MESSAGE(Const::UM_DIFFICULTY_UP, OnDifficultyUp)
    ON_MESSAGE(Const::UM_GAME_OVER, OnGameOver)
    ON_MESSAGE(Const::UM_SCORE, OnScore)
    ON_WM_ACTIVATE()
    ON_WM_CTLCOLOR()
    ON_WM_PAINT()
    ON_WM_TIMER()
END_MESSAGE_MAP()

/**
 * 构造方法。
 * @param parent    父窗口
 */
MainWindow::MainWindow(CWnd* parent) :
    CDialog(IDD_MAIN_WINDOW, parent),
    mGame(NULL),
    mGameBoard(Const::GAME_BOARD_WIDTH, Const::GAME_BOARD_HEIGHT),
    mPreview(Const::PREVIEW_WIDTH, Const::PREVIEW_HEIGHT) {
    mImage.LoadFromResource(AfxGetInstanceHandle(), IDB_MAIN_WINDOW);
}

/**
 * 析构方法。
 */
MainWindow::~MainWindow() {
    // 删除游戏
    delete mGame;
}

/**
 * 窗口活动事件的响应方法。
 * @param state 为 WA_INACTIVE 则表示窗口进入不活动状态
 */
void MainWindow::OnActivate(UINT state, CWnd*, BOOL) {
    Game::Status status = mGame->GetStatus();
    if (status == Game::PLAYING && state == WA_INACTIVE) {
        this->OnButtonPauseClicked();
    }
}

/**
 * "播放音乐"按钮的单击响应方法。
 */
void MainWindow::OnButtonMusicClicked() {
    BOOL playingMusic = mGame->PlayMusic();
    CMFCButton* buttonMusic = (CMFCButton*)CDialog::GetDlgItem(IDC_BUTTON_MUSIC);
    CString text;
    if (playingMusic) {
        buttonMusic->SetImage(IDB_BUTTON_MUSIC_STOP);
    } else {
        buttonMusic->SetImage(IDB_BUTTON_MUSIC_PLAY);
    }
}

/**
 * "暂停"按钮的单击响应方法。
 */
void MainWindow::OnButtonPauseClicked() {
    mGame->Pause();
    Game::Status status = mGame->GetStatus();
    CMFCButton* buttonPause = (CMFCButton*)CDialog::GetDlgItem(IDC_BUTTON_PAUSE);
    if (status == Game::PAUSED) {
        buttonPause->SetImage(IDB_BUTTON_RESUME);
    } else if (status == Game::PLAYING) {
        buttonPause->SetImage(IDB_BUTTON_PAUSE);
    }
}

/**
 * "开始"按钮的单击响应方法。
 */
void MainWindow::OnButtonStartClicked() {
    // 游戏开始
    mGame->Start();

    // 设置按钮状态
    CMFCButton* buttonPause = (CMFCButton*)CDialog::GetDlgItem(IDC_BUTTON_PAUSE);
    buttonPause->EnableWindow(TRUE);

    // 设置按钮图片
    buttonPause->SetImage(IDB_BUTTON_PAUSE);
    buttonPause->Invalidate(FALSE);

    // 设置状态栏
    this->OnDifficultyUp(1);
    this->OnScore(0);
}

/**
 * 控件颜色事件的响应方法。
 * @param drawer    绘图者
 * @param window    控件
 * @param ctlColor  控件类型
 * @return 控件的背景画刷
 */
HBRUSH MainWindow::OnCtlColor(CDC* drawer, CWnd* window, UINT ctlColor) {
    HBRUSH brush = CDialog::OnCtlColor(drawer, window, ctlColor);
    int id = window->GetDlgCtrlID();
    if (ctlColor == CTLCOLOR_STATIC && id == IDC_LABEL_HELP) {
        drawer->SetBkMode(TRANSPARENT);
        brush = (HBRUSH)::GetStockObject(NULL_BRUSH);
    }
    return brush;
}

/**
 * 难度增加事件的响应方法。
 * @param wParam    难度
 * @return 总是零
 */
LRESULT MainWindow::OnDifficultyUp(WPARAM wParam, LPARAM) {
    CString text, temp;
    text.LoadString(NULL, IDS_DIFFICULTY);
    temp.Format(_T("%d"), wParam);
    text += temp;
    mStatusBar.SetText(text, 0, 0);

    return 0;
}

/**
 * 游戏结束事件的响应方法。
 * @param wParam    胜利则为 TRUE，否则为 FALSE
 * @return 总是零
 */
LRESULT MainWindow::OnGameOver(WPARAM wParam, LPARAM) {
    if (wParam) {
        AfxMessageBox(IDS_WON, MB_ICONINFORMATION);
    } else {
        AfxMessageBox(IDS_LOST, MB_ICONINFORMATION);
    }
    CDialog::GetDlgItem(IDC_BUTTON_PAUSE)->EnableWindow(FALSE);

    return 0;
}

/**
 * 初始化事件的响应方法。
 * @return 总是 TRUE
 */
BOOL MainWindow::OnInitDialog() {
    CDialog::OnInitDialog();

    // 创建状态栏
    CRect windowRect;
    mStatusBar.Create(WS_CHILD | WS_VISIBLE | CCS_BOTTOM, windowRect, this, AFX_IDW_STATUS_BAR);

    // 设置状态栏的格的宽度
    CDialog::GetWindowRect(windowRect);
    int lblWidth = (windowRect.right - windowRect.left) / Const::STATUS_BAR_PART_COUNT;
    int* parts = new int[Const::STATUS_BAR_PART_COUNT];
    for (int i = 0; i < Const::STATUS_BAR_PART_COUNT; i++) {
        parts[i] = lblWidth * (i + 1);
    }
    mStatusBar.SetParts(Const::STATUS_BAR_PART_COUNT, parts);
    delete[] parts;

    // 设置状态栏第1格的文字
    this->OnDifficultyUp(1);

    // 设置状态栏第2格的文字
    this->OnScore(0);

    // 状态游戏区域
    CRect gameBoardRect(Const::GAME_BOARD_X, Const::GAME_BOARD_Y,
        Const::GAME_BOARD_X + Const::GAME_BOARD_WIDTH, Const::GAME_BOARD_Y + Const::GAME_BOARD_HEIGHT);
    mGameBoard.Create(NULL, NULL, WS_CHILD | WS_VISIBLE, gameBoardRect, this, 0);

    // 创建预览区域
    CRect previewRect(Const::PREVIEW_X, Const::PREVIEW_Y,
        Const::PREVIEW_X + Const::PREVIEW_WIDTH, Const::PREVIEW_Y + Const::PREVIEW_HEIGHT);
    mPreview.Create(NULL, NULL, WS_CHILD | WS_VISIBLE, previewRect, this, 0);

    // 创建游戏
    mGame = new Game(this, &mGameBoard, mGameBoard.GetDrawer(), &mPreview, mPreview.GetDrawer());

    return TRUE;  // return TRUE  unless you set the focus to a control
}

/**
 * 重绘事件的响应方法。
 */
void MainWindow::OnPaint() {
    CClientDC drawer(this);
    mImage.Draw(drawer.GetSafeHdc(), 0, 0);
    CDialog::OnPaint();
}

/**
 * 得分事件的响应方法。
 * @param wParam    得分
 * @return 总是零
 */
LRESULT MainWindow::OnScore(WPARAM wParam, LPARAM) {
    CString text, temp;
    text.LoadString(NULL, IDS_SCORE);
    temp.Format(_T("%d"), wParam);
    text += temp;
    mStatusBar.SetText(text, 1, 0);

    return 0;
}

/**
 * 定时器事件的响应方法。
 */
void MainWindow::OnTimer(UINT_PTR) {
    mGame->OnTimer();
}

/**
 * 在翻译事件之前调用的方法。
 * @param msg   事件
 * @return 事件在此被处理则返回 TRUE，否则返回 FALSE
 */
BOOL MainWindow::PreTranslateMessage(MSG* msg) {
    if (msg->message == WM_KEYDOWN) {
        return mGame->OnKeyPressed(msg->wParam);
    }

    return CDialog::PreTranslateMessage(msg);
}
